package com.hboxs.asl;

import org.apache.lucene.index.IndexReader;
import org.apache.lucene.search.FieldCache;
import org.apache.lucene.search.FieldComparator;
import org.apache.lucene.search.FieldComparatorSource;

import java.io.IOException;

/**
 * @author Dinfeng
 */
public class CustomPriceComparator extends FieldComparatorSource {

    private Integer startPrice;
    private Integer endPrice;

    public CustomPriceComparator() {
        super();
    }

    public CustomPriceComparator(Integer startPrice, Integer endPrice) {
        this.startPrice = startPrice;
        this.endPrice = endPrice;
    }

    @Override
    public FieldComparator newComparator(String fieldname, int numHits, int sortPos, boolean reversed) throws IOException {

        return new ProductCategoryComparator(numHits, fieldname);
    }

    // 我们自定义排序类DateValComparator 继承FieldComparator 类实现里面的方法

    final class ProductCategoryComparator extends FieldComparator {
        private Integer[] values;
        private int[] currentReaderValues;
        private final String field;
        private Integer bottom;

        ProductCategoryComparator(int numHits, String field) {
            this.values = new Integer[numHits];
            this.field = field;
        }

        // 第三步：调用的比较方法，如果查询结果没有超过超过了我们设定的总行数那么会调用这个方法进行比较
        public int compare(int slot1, int slot2) {
            try {
                Integer val1 = values[slot1];
                Integer val2 = values[slot2];
                if (null == val1) {
                    if (null == val2) {
                        return 0;
                    }
                    return -1;
                }
                if (null == val2) {
                    return 1;
                }
                if (isInRange(val1) && isInRange(val2)) {
                    return 0;
                }
                if (isInRange(val1) && !isInRange(val2)) {
                    return 1;
                }
                if (!isInRange(val1) && isInRange(val2)) {
                    return -1;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }

            return 0;
        }

        // Lucene的查询结果是放在优先队列里面的，优先对象是通过compare进行比较，如果查询结果超过了我们设定的总行数那么会第二步调用这个方法
        public int compareBottom(int doc) {
            try {
                Integer val2 = this.currentReaderValues[doc];
                Integer tempBottom = this.bottom;
                if (tempBottom == null) {
                    if (val2 == null) {
                        return 0;
                    }
                    return -1;
                }
                if (val2 == null) {
                    return 1;
                }
                if (isInRange(val2)) {
                    return 1;
                }
                if (isInRange(tempBottom)) {
                    return -1;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            return 0;
        }

        // 第二步：调用的方法，将currentReaderValues时间数组中的第一个值 copy到
        // values中对应的位置中,注意此方法第一次调用了两次
        public void copy(int slot, int doc) {
            this.values[slot] = this.currentReaderValues[doc];
        }

        // 第一步：调用的方法，本方法是得到所有搜索到的时间数组并初始化currentValues,docBase用来确定需要几个数组
        public void setNextReader(IndexReader reader, int docBase) throws IOException {
            this.currentReaderValues = FieldCache.DEFAULT.getInts(reader, this.field);
        }

        // 如果查询结果超过了我们设定的总行数那么会第一步调用这个方法
        public void setBottom(int bottom) {
            this.bottom = this.values[bottom];
        }

        // 要输出的排好序的结果集
        public Comparable value(int slot) {
            return this.values[slot];
        }

        public boolean isInRange(Integer slot) {
            return slot >= startPrice && slot <= endPrice;
        }

    }
}
